﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using SolutionExtender.AppCode;
using SolutionExtender.Interfaces;
using System.IO;

namespace McTools.SolutionExtender.BusinessUnitPlugin
{
    public partial class BusinessUnitControl : UserControl, IExportControl
    {
        #region Variables

        /// <summary>
        /// Microsoft Dynamics CRM 2011 Organization service
        /// </summary>
        private readonly IOrganizationService _service;

        /// <summary>
        /// Indicates if this control found rules
        /// </summary>
        private bool _hasData;

        private readonly List<TreeNode> _checkedTreeNodes;

        private Guid _rootBusinessUnitId;

        #endregion Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of class DuplicateDetectionRuleControl
        /// </summary>
        /// <param name="service">Microsoft Dynamics CRM 2011 Organization service</param>
        public BusinessUnitControl(IOrganizationService service)
        {
            _service = service;
            _checkedTreeNodes = new List<TreeNode>();
            InitializeComponent();
        }

        #endregion Constructor

        private void BusinessUnitControlLoad(object sender, EventArgs e)
        {
            var qe = new QueryExpression("businessunit");
            qe.Criteria.AddCondition("parentbusinessunitid", ConditionOperator.Null);
            qe.Criteria.AddCondition("isdisabled", ConditionOperator.Equal, false);
            qe.ColumnSet = new ColumnSet("address1_addresstypecode",
                                         "address1_city",
                                         "address1_country",
                                         "address1_county",
                                         "address1_fax",
                                         "address1_latitude",
                                         "address1_line1",
                                         "address1_line2",
                                         "address1_line3",
                                         "address1_longitude",
                                         "address1_name",
                                         "address1_postalcode",
                                         "address1_postofficebox",
                                         "address1_shippingmethodcode",
                                         "address1_stateorprovince",
                                         "address1_telephone1",
                                         "address1_telephone2",
                                         "address1_telephone3",
                                         "address1_upszone",
                                         "address1_utcoffset",
                                         "address2_addresstypecode",
                                         "address2_city",
                                         "address2_country",
                                         "address2_county",
                                         "address2_fax",
                                         "address2_latitude",
                                         "address2_line1",
                                         "address2_line2",
                                         "address2_line3",
                                         "address2_longitude",
                                         "address2_name",
                                         "address2_postalcode",
                                         "address2_postofficebox",
                                         "address2_shippingmethodcode",
                                         "address2_stateorprovince",
                                         "address2_telephone1",
                                         "address2_telephone2",
                                         "address2_telephone3",
                                         "address2_upszone",
                                         "address2_utcoffset",
                                         "costcenter",
                                         "creditlimit",
                                         "description",
                                         "divisionname",
                                         "emailaddress",
                                         "fileasname",
                                         "ftpsiteurl",
                                         "name",
                                         "picture",
                                         "stockexchange",
                                         "tickersymbol",
                                         "utcoffset",
                                         "websiteurl");

            var results = _service.RetrieveMultiple(qe);

            _rootBusinessUnitId = results.Entities[0].Id;

            FillTreeView(null, results);

            if(tvBus.Nodes.Count == 1)
            {
                _hasData = false;
            }
        }

        private void FillTreeView(TreeNode parentNode, EntityCollection items)
        {
            foreach (var bu in items.Entities)
            {
                var node = new TreeNode(bu["name"].ToString()) { Tag = bu, ImageIndex = 0, SelectedImageIndex = 0};

                if (parentNode == null)
                {
                    tvBus.Nodes.Add(node);
                }
                else
                    parentNode.Nodes.Add(node);

                var qe = new QueryExpression("businessunit");
                qe.Criteria.AddCondition("parentbusinessunitid", ConditionOperator.Equal, bu.Id);
                qe.Criteria.AddCondition("isdisabled", ConditionOperator.Equal, false);
                qe.ColumnSet = new ColumnSet("address1_addresstypecode",
                                         "address1_city",
                                         "address1_country",
                                         "address1_county",
                                         "address1_fax",
                                         "address1_latitude",
                                         "address1_line1",
                                         "address1_line2",
                                         "address1_line3",
                                         "address1_longitude",
                                         "address1_name",
                                         "address1_postalcode",
                                         "address1_postofficebox",
                                         "address1_shippingmethodcode",
                                         "address1_stateorprovince",
                                         "address1_telephone1",
                                         "address1_telephone2",
                                         "address1_telephone3",
                                         "address1_upszone",
                                         "address1_utcoffset",
                                         "address2_addresstypecode",
                                         "address2_city",
                                         "address2_country",
                                         "address2_county",
                                         "address2_fax",
                                         "address2_latitude",
                                         "address2_line1",
                                         "address2_line2",
                                         "address2_line3",
                                         "address2_longitude",
                                         "address2_name",
                                         "address2_postalcode",
                                         "address2_postofficebox",
                                         "address2_shippingmethodcode",
                                         "address2_stateorprovince",
                                         "address2_telephone1",
                                         "address2_telephone2",
                                         "address2_telephone3",
                                         "address2_upszone",
                                         "address2_utcoffset",
                                         "costcenter",
                                         "creditlimit",
                                         "description",
                                         "divisionname",
                                         "emailaddress",
                                         "fileasname",
                                         "ftpsiteurl",
                                         "name",
                                         "parentbusinessunitid",
                                         "picture",
                                         "stockexchange",
                                         "tickersymbol",
                                         "utcoffset",
                                         "websiteurl");

                var results = _service.RetrieveMultiple(qe);

                FillTreeView(node, results);
            }
        }

        public XmlNodeList GetSelectedItems()
        {
            if (_checkedTreeNodes.Count == 0 && _hasData)
            {
                pnlError.Visible = true;
                return null;
            }

            pnlError.Visible = false;
            var stringifiedXml = new StringBuilder();
            stringifiedXml.Append("<Root>");

            foreach (var item in _checkedTreeNodes)
            {
                var entity = (Entity) item.Tag;

                if (entity.Contains("parentbusinessunitid"))
                {
                    stringifiedXml.Append(string.Format("<BusinessUnit name=\"{0}\">",entity["name"]));
                    if (((EntityReference) entity["parentbusinessunitid"]).Id == _rootBusinessUnitId)
                    {
                        entity["parentbusinessunitid"] = new EntityReference("businessunit", Guid.Empty);
                    }

                    var tempDoc = new XmlDocument();
                    tempDoc.LoadXml(BuildReturnedString(entity));

                    stringifiedXml.Append(tempDoc.DocumentElement.OuterXml);
                    stringifiedXml.Append("</BusinessUnit>");
                }
                else if(_checkedTreeNodes.Count == 1)
                {
                    pnlError.Visible = true;
                    return null;
                }
            }

            stringifiedXml.Append("</Root>");

            var doc = new XmlDocument();
            doc.LoadXml(stringifiedXml.ToString());

            return doc.SelectNodes("Root/BusinessUnit");
        }

        private string BuildReturnedString(Entity entity)
        {
            var mStream = new MemoryStream();
            var serializer = new DataContractSerializer(typeof (Entity),
                                                        null,
                                                        int.MaxValue,
                                                        false,
                                                        false,
                                                        null,
                                                        new KnownTypesResolver());

            var writer = new XmlTextWriter(mStream, Encoding.UTF8)
                             {
                                 Formatting = Formatting.Indented
                             };
            serializer.WriteObject(writer, entity);
            writer.Flush();
            mStream.Seek(0, SeekOrigin.Begin);
            var reader = new StreamReader(mStream);
            return reader.ReadToEnd();
        }

        private void TvBusAfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Checked)
                _checkedTreeNodes.Add(e.Node);
            else if (_checkedTreeNodes.Contains(e.Node))
                _checkedTreeNodes.Remove(e.Node);
                
            foreach(TreeNode node in e.Node.Nodes)
            {
                node.Checked = e.Node.Checked;
            }
        }

        
    }
}
